home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / smaltalk / gnu_st.lha / gnu_st / smalltalk-1.1.1 / stix / socket.c < prev    next >
C/C++ Source or Header  |  1990-05-24  |  6KB  |  280 lines

  1. /* Copyright    Massachusetts Institute of Technology    1988    */
  2. /*
  3.  * THIS IS AN OS DEPENDENT FILE! It should work on 4.2BSD derived
  4.  * systems.  VMS and System V should plan to have their own version.
  5.  *
  6.  * This code was cribbed from lib/X/XConnDis.c.
  7.  * Compile using   
  8.  *                    % cc -c socket.c -DUNIXCONN
  9.  */
  10.  
  11. #include <stdio.h>
  12. #ifndef COMPILE_ONLY
  13. #include <Xos.h>
  14. #include <Xproto.h>
  15. #else
  16. #include <sys/types.h>
  17. #endif
  18. #include <errno.h>
  19. #include <netinet/in.h>
  20. #include <sys/ioctl.h>
  21. #include <netdb.h> 
  22. #include <sys/socket.h>
  23. #ifndef hpux
  24. #include <netinet/tcp.h>
  25. #endif
  26. #include <sys/types.h>
  27. #include <sys/time.h>
  28.  
  29. static int connect_to_server();
  30. static void byte();
  31. static void word();
  32. static void lword();
  33. static void nBytes();
  34. static u_char getByte();
  35. static u_short getWord();
  36. static u_long getLword();
  37. static int waitForSocket();
  38.  
  39. extern int errno;        /* Certain (broken) OS's don't have this */
  40.                 /* decl in errno.h */
  41.  
  42. #ifdef UNIXCONN
  43. #include <sys/un.h>
  44. #ifndef X_UNIX_PATH
  45. #define X_UNIX_PATH "/tmp/.X11-unix/X"
  46. #endif /* X_UNIX_PATH */
  47. #endif /* UNIXCONN */
  48. void bcopy();
  49.  
  50. void defineSocket()
  51. {
  52.   defineCFunc("connectToServer", connect_to_server);
  53.   defineCFunc("byte", getByte);
  54.   defineCFunc("word", getWord);
  55.   defineCFunc("long", getLword);
  56.   defineCFunc("putByte", byte);
  57.   defineCFunc("putWord", word);
  58.   defineCFunc("putLong", lword);
  59.   defineCFunc("putBytes", nBytes);
  60.   defineCFunc("waitForSocket", waitForSocket);
  61. }
  62.  
  63. static void byte(s, v)
  64. int s;
  65. u_char v;
  66. {
  67.   if (write(s, &v, 1) < 0) {
  68.     perror("write byte");
  69.   }
  70. }
  71.  
  72. static void word(s, v)
  73. int s;
  74. u_short v;
  75. {
  76.   if (write(s, &v, 2) < 0) {
  77.     perror("write word");
  78.   }
  79. }
  80.  
  81. static void lword(s, v)
  82. int s;
  83. u_long v;
  84. {
  85.   if (write(s, &v, 4) < 0) {
  86.     perror("write long");
  87.   }
  88. }
  89.  
  90. static void nBytes(s, n, byteStr)
  91. int s;
  92. int n;
  93. char *byteStr;
  94. {
  95.   if (write(s, byteStr, n) < 0) {
  96.     perror("write bytes");
  97.   }
  98. }
  99.  
  100. static u_char getByte(s)
  101. {
  102.   u_char v;
  103.   if (read(s, &v, 1) < 0) {
  104.     perror("read byte");
  105.   }
  106.  
  107.   return (v);
  108. }
  109.  
  110. static u_short getWord(s)
  111. {
  112.   u_short v;
  113.   if (read(s, &v, 2) < 0) {
  114.     perror("read short");
  115.   }
  116.  
  117.   return (v);
  118. }
  119.  
  120. static u_long getLword(s)
  121. {
  122.   u_long v;
  123.   if (read(s, &v, 4) < 0) {
  124.     perror("read long");
  125.   }
  126.  
  127.   return (v);
  128. }
  129.  
  130.  
  131. /* 
  132.  * Attempts to connect to server, given host and display. Returns file 
  133.  * descriptor (network socket) or 0 if connection fails.
  134.  */
  135.  
  136. static int connect_to_server (host, display)
  137.      char *host;
  138.      int display;
  139. {
  140.   struct sockaddr_in inaddr;    /* INET socket address. */
  141.   struct sockaddr *addr;        /* address to connect to */
  142.   struct hostent *host_ptr;
  143.   int addrlen;            /* length of address */
  144. #ifdef UNIXCONN
  145.   struct sockaddr_un unaddr;    /* UNIX socket address. */
  146. #endif
  147.   extern char *getenv();
  148.   extern struct hostent *gethostbyname();
  149.   int fd;                /* Network socket */
  150.  
  151. #ifndef COMPILE_ONLY
  152.   {
  153. #ifdef UNIXCONN
  154.     if ((host[0] == '\0') || 
  155.     (strcmp("unix", host) == 0)) {
  156.     /* Connect locally using Unix domain. */
  157.     unaddr.sun_family = AF_UNIX;
  158.     (void) strcpy(unaddr.sun_path, X_UNIX_PATH);
  159.     sprintf(&unaddr.sun_path[strlen(unaddr.sun_path)], "%d", display);
  160.     addr = (struct sockaddr *) &unaddr;
  161.     addrlen = strlen(unaddr.sun_path) + 2;
  162.     /*
  163.      * Open the network connection.
  164.      */
  165.     if ((fd = socket((int) addr->sa_family, SOCK_STREAM, 0)) < 0)
  166.         return(-1);        /* errno set by system call. */
  167.     } else
  168. #endif
  169.     {
  170.       /* Get the statistics on the specified host. */
  171.       if ((inaddr.sin_addr.s_addr = inet_addr(host)) == -1) 
  172.     {
  173.       if ((host_ptr = gethostbyname(host)) == NULL) 
  174.         {
  175.           /* No such host! */
  176.           errno = EINVAL;
  177.           return(-1);
  178.         }
  179.       /* Check the address type for an internet host. */
  180.       if (host_ptr->h_addrtype != AF_INET) 
  181.         {
  182.           /* Not an Internet host! */
  183.           errno = EPROTOTYPE;
  184.           return(-1);
  185.         }
  186.       /* Set up the socket data. */
  187.       inaddr.sin_family = host_ptr->h_addrtype;
  188.       bcopy((char *)host_ptr->h_addr, 
  189.         (char *)&inaddr.sin_addr, 
  190.         sizeof(inaddr.sin_addr));
  191.     } 
  192.       else 
  193.     {
  194.       inaddr.sin_family = AF_INET;
  195.     }
  196.       addr = (struct sockaddr *) &inaddr;
  197.       addrlen = sizeof (struct sockaddr_in);
  198.       inaddr.sin_port = display + X_TCP_PORT;
  199.       inaddr.sin_port = htons(inaddr.sin_port);
  200.       /*
  201.        * Open the network connection.
  202.        */
  203.       if ((fd = socket((int) addr->sa_family, SOCK_STREAM, 0)) < 0){
  204.     return(-1);        /* errno set by system call. */}
  205.       /* make sure to turn off TCP coalescence */
  206. #ifdef TCP_NODELAY
  207.       {
  208.     int mi = 1;
  209.     setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &mi, sizeof (int));
  210.       }
  211. #endif
  212.     }
  213.  
  214.     /*
  215.      * Changed 9/89 to retry connection if system call was interrupted.  This
  216.      * is necessary for multiprocessing implementations that use timers,
  217.      * since the timer results in a SIGALRM.    -- jdi
  218.      */
  219.     while (connect(fd, addr, addrlen) == -1) {
  220.     if (errno != EINTR) {
  221.           (void) close (fd);
  222.           return(-1);         /* errno set by system call. */
  223.     }
  224.       }
  225.   }
  226.   /*
  227.    * Return the id if the connection succeeded.
  228.    */
  229. #endif
  230.   return(fd);
  231. }
  232.  
  233. /*
  234.  *    static int waitForSocket(fd, timeout)
  235.  *
  236.  * Description
  237.  *
  238.  *    Waits for some data to be available on the given socket.
  239.  *
  240.  * Inputs
  241.  *
  242.  *    fd    : File descriptor for socket to wait on
  243.  *    timeout: 
  244.  *        Value in milliseconds to wait before timing out.  If zero, wait
  245.  *        until there's input with no timeout.
  246.  *
  247.  * Outputs
  248.  *
  249.  *    True if there was input available, false if it timed out.
  250.  */
  251. static int waitForSocket(fd, timeout)
  252. int    fd, timeout;
  253. {
  254.   struct timeval time, *timePtr;
  255. #ifdef SUNOS4
  256.   fd_set    fds;
  257.  
  258.   FD_ZERO(&fds);
  259.   FD_SET(fd, &fds);
  260. #else
  261.   int        fds;
  262.  
  263.   fds = 1 << (fd - 1);
  264. #endif
  265.  
  266.   if (timeout) {
  267.     time.tv_sec = timeout / 1000;
  268.     time.tv_usec = (timeout % 1000) * 1000;
  269.     timePtr = &time;
  270.   } else {
  271.     timePtr = NULL;
  272.   }
  273.  
  274.   if (select(getdtablesize(), &fds, NULL, NULL, timePtr)) {
  275.     return (1);
  276.   } else {
  277.     return (0);
  278.   }
  279. }
  280.